(function (global) {
  const uploadHelper = (function () {
    let _options = {
      /** 存储对象平台：COS，OSS */
      objPlatform: 'OSS',
      /** 获取签名地址 */
      signUrl: '',
      /** 是否开启缓存 */
      cacheToken: true,
      /** 缓存请求结果 */
      cacheResult: null,
      /** 有效期（秒） */
      expire: 0,
      /** 附带请求数据 */
      signData: null,
      /** 文件名格式化 */
      fileNameFormat(filename = '') {
        // if (!filename) {
        //   return `file-${Date.now()}`;
        // }
        // const ext = filename.substring(
        //   filename.lastIndexOf('.'),
        //   filename.length
        // );
        return filename || `file-${dateStr()}-${randomStr(4)}`;
      },
      /** 自定义请求函数 */
      request({ url, data, callback } = {}) {},
    };

    function randomStr(num) {
      const dict = '1234567890abcdef';
      const strs = [];
      for (var i = 0; i < num; i++) {
        strs.push(dict[Math.floor(Math.random() * 16)]);
      }
      return strs.join('');
    }

    function zeroFill(num, length = 2) {
      const len = (num + '').length;
      const diff = length - len;
      if (diff > 0) {
        return Array(diff).fill('0').join('') + num;
      }
      return num;
    }

    function dateStr() {
      const date = new Date();
      const year = date.getFullYear();
      const month = zeroFill(date.getMonth() + 1);
      const day = zeroFill(date.getDay());
      const hours = zeroFill(date.getHours());
      const minutes = zeroFill(date.getMinutes());
      const seconds = zeroFill(date.getSeconds());
      return `${year}${month}${day}${hours}${minutes}${seconds}`;
    }

    function getFileName(filename) {
      return _options.fileNameFormat(filename);
    }

    function setOptions(options) {
      _options = { ..._options, ...options };
    }

    function init(options = {}) {
      setOptions(options);
    }

    const pretreatmentMethod = {
      /** 阿里云的表单数据 */
      OSS: function (data, useFormData = true) {
        const key = data.key || data.localKey;
        let formData = {
          key,
          policy: data.policy,
          OSSAccessKeyId: data.accessId,
          success_action_status: '200',
          callback: '',
          signature: data.signature,
        };
        if (useFormData) {
          const formDataBody = new FormData();
          Object.keys(formData).forEach((key) => {
            if (formData[key] instanceof Array) {
              formData[key].forEach((item) => {
                formDataBody.append(key, item);
              });
              return;
            }
            formDataBody.append(key, formData[key]);
          });
          formData = formDataBody;
        }
        return {
          action: data.host,
          key,
          filename: data.filename || key,
          domain: data.domain || '',
          fileUrl: `${data.domain}${key}`,
          formData,
        };
      },
    };

    function handleResult(options) {
      const newData = Math.round(new Date() / 1000);
      const filename = options.fileNameFormat
        ? options.fileNameFormat(options.filename)
        : options.filename;
      const request = options.request;
      const isMultiple = options.isMultiple;
      const fileTotal = options.fileTotal;
      const callback = options.callback;
      if (request) {
        const func = pretreatmentMethod[options.objPlatform];

        // 走缓存
        if (
          _options.cacheToken &&
          _options.expire > newData &&
          _options.cacheResult
        ) {
          callback(
            func({
              ..._options.cacheResult,
              filename: options.filename,
              localKey: filename,
            })
          );
          return;
        }

        request({
          url: options.signUrl,
          data: options.signData,
          callback: function (data) {
            if (!data) {
              throw new Error('data is null');
            }
            if (_options.cacheToken) {
              _options.cacheResult = data;
              _options.expire = data.expire || 0;
            }
            if (func && callback) {
              callback(
                func({
                  ...data,
                  filename: options.filename,
                  localKey: filename,
                })
              );
            } else {
              throw new Error('callback or objPlatform not exist');
            }
          },
        });
      }
    }

    function getUploadXhr(options) {
      if (typeof options === 'function') {
        handleResult({ ..._options, callback: options });
      } else if (typeof options === 'object') {
        handleResult({ ..._options, ...options });
      }
    }

    async function advanceCacheResult() {
      const request = _options.request;
      return new Promise((resolve, reject) => {
        request({
          url: _options.signUrl,
          data: _options.signData,
          callback: function (data) {
            if (!data) {
              reject(new Error('data is null'));
              return;
            }
            if (_options.cacheToken) {
              _options.cacheResult = data;
              _options.expire = data.expire || 0;
            }
            resolve(data);
          },
        });
      });
    }

    return {
      init,
      setOptions,
      getUploadXhr,
      advanceCacheResult,
      randomStr,
      dateStr,
      getFileName,
    };
  })();
  global.UploadHelper = uploadHelper;
})(window || this);
